
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <stdio.h>
#include <string.h>

#include "normal_udp.h"

#define EXAMPLE_PORT 8888
#define EXAMPLE_GROUP "239.239.239.5"

/* only this extern C statement when libpacket_handler_gcc.a or .so which are compiled by gcc */
// #ifdef __cplusplus
// extern "C" {
// #endif

// #ifdef __cplusplus
// }
// #endif

int main(int argc, char *argv[])
{
	struct sockaddr_in addr;
	int addrlen, sock, cnt;
	struct ip_mreq mreq;
	char message[2048];
	//    char output_data[256];
	//    int result = 0;

	/* set up socket */
	sock = socket(AF_INET, SOCK_DGRAM, 0);
	if (sock < 0)
	{
		perror("socket");
		return -1;
	}

	memset(&addr, 0x00, sizeof(addr));
	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = htonl(INADDR_ANY);
	addr.sin_port = htons(EXAMPLE_PORT);
	addrlen = sizeof(addr);

	/* receive */
	if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
	{
		perror("bind");
		return -1;
	}
	mreq.imr_multiaddr.s_addr = inet_addr(EXAMPLE_GROUP);
	mreq.imr_interface.s_addr = htonl(INADDR_ANY);
	if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
	{
		perror("setsockopt mreq");
		return -1;
	}

	while (1)
	{
		cnt = recvfrom(sock, message, sizeof(message), 0, (struct sockaddr *)&addr, (socklen_t *)&addrlen);
		if (cnt < 0)
		{
			perror("recvfrom");
			return -1;
		}
		else if (cnt < 20 && cnt > 170)
		{
			printf("<ERR> abnormal payload size:%d\n", cnt);
			break;
		}

		st_best_depth_update *best_depth_update = (st_best_depth_update *)message;

		printf("%s, %d.%d, %.2f/%d %.1f/%d, %d_%.1f\n",
			   best_depth_update->contract_id,

			   best_depth_update->update_time,
			   best_depth_update->update_time_usec,
			   
			   (double)(((ntohl(best_depth_update->turnover1) & 0x3fffffff) << 26) | (ntohl(best_depth_update->turnover2) & 0x3fffffff)) ,
			   (ntohl(best_depth_update->open_interest) & 0x3fffffff) / ntohs(best_depth_update->decimal_in_best),
			   (float)((ntohl(best_depth_update->last_price) & 0x3fffffff) / ntohl(best_depth_update->decimal_in_best)),
			   (ntohl(best_depth_update->volumn) & 0x3fffffff) / ntohs(best_depth_update->decimal_in_best),

			   (ntohl(best_depth_update->bid5 >> 32) & 0x3fffffff) / ntohs(best_depth_update->decimal_in_best),
			   (float)(ntohl(best_depth_update->bid5) & 0x3fffffff) / ntohs(best_depth_update->decimal_in_best)
		);

	}

	return 0;
}
